/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;
import javax.microedition.lcdui.game.Sprite;
import javax.microedition.lcdui.game.TiledLayer;

/**
 *
 * @author tien
 */
public class Map extends BaseRMS{
    
    public void loadMap() throws Exception {
        try {
            // Will call either loadData() or createDefaultData()
            this.open();

            if (getNumRecords() > 0) {
                loadData();
            } else {
                createDefaultData();
            }

            // Close
            if (this.getRecordStore() != null)
                this.close();
            } catch (Exception e) {
            throw new Exception("Error load map" + e);
        }
    }
    GameScreen canvas;
    TiledLayer tlBase;
    
    TiledLayer tlWater;
    TiledLayer tlThings;
    TileAnimationTask waterAnimator;
    
    Vector spawnPoints;
    
    Point home;
    
    public int getX() {
        return this.tlBase.getX();
    }
    
    public int getY() {
        return this.tlBase.getY();
    }
    
    public int getHomeX() {
        return home.x;
    }
    
    public int getHomeY() {
        return home.y;
    }
    
    public int getWidth() {
        return this.tlBase.getWidth();
    }
    
    public int getHeight() {
        return this.tlBase.getHeight();
    }
    
    private int getCellWidth() {
        return tlBase.getCellWidth();
    }
    
    private int getCellHeight() {
        return tlBase.getCellHeight();
    }
    
    public Map(GameScreen canvas) throws IOException {
        this.canvas = canvas;
    }
    
    public String getRMSName() {
      return "MushroomGameMap";
  }
    
    public void createSpawnPoint() {
        this.spawnPoints = new Vector();
        
        int rows = this.tlThings.getRows();
        int columns = this.tlThings.getColumns();
        int nmbSigns = 0;
        
        for (int i = 0; i < columns - 1; i++) 
            for (int j = 0; j < rows - 1; j++){
                if (this.tlThings.getCell(i, j) == ThingType.SIGN) {
                    this.spawnPoints.addElement(new Point(i, j));
                }
                else if (this.tlThings.getCell(i, j) == ThingType.HOME) {
                    this.home = new Point(i, j);
                }
            }
    }

    int getNumberSpawnPoint() {
        return this.spawnPoints.size();
    }

    Point getSpawnPoint(int number) {
        return (Point)this.spawnPoints.elementAt(number);
    }

    void stop() {
        this.waterAnimator.setMoving(false);
    }

    void start() {
        this.waterAnimator.setMoving(true);
    }

    int getThing(int indexX, int indexY) {
        return tlThings.getCell(indexX, indexY);
    }

    void setThing(int indexX, int indexY, int thing) {
        tlThings.setCell(indexX, indexY, thing);
    }

    Vector getThingIndexs(int x, int y, int width, int height) {
        Vector points = new Vector();
            
        if (x >= getWidth() || y >= getHeight())
            return points;
        else {
            int indexX;
            int indexY;
            
            indexX = x / getCellWidth();
            indexY = y / getCellHeight();
            points.addElement(new Point(indexX, indexY));
            
            indexX = (x+width) / getCellWidth();
            indexY = y / getCellHeight();
            points.addElement(new Point(indexX, indexY));
            
            indexX = x / getCellWidth();
            indexY = (y+height) / getCellHeight();
            points.addElement(new Point(indexX, indexY));
            
            indexX = (x+width) / getCellWidth();
            indexY = (y+height) / getCellHeight();
            points.addElement(new Point(indexX, indexY));
            
            return points;
        }
    }

    boolean checkCollide(Sprite sprite) {
        return sprite.getX() < 0 || sprite.getY() < 0
                || sprite.getX() > (getWidth() - sprite.getWidth())
                || sprite.getY() > (getHeight() - sprite.getHeight())
                || this.checkCollideWithWater(sprite);
    }


    boolean checkCollideWithWater(Sprite sprite) {
        return sprite.collidesWith(tlWater, true);
    }

    boolean checkCollideWithThings(Sprite sprite) {
        return sprite.collidesWith(tlThings, true);
    }
    
    void loadData() throws Exception {
        try {
            byte[] record = this.getRecordStore().getRecord(1);
            DataInputStream istream = new DataInputStream(new ByteArrayInputStream(record,0,record.length));

            int column = istream.readInt();
            int row = istream.readInt();

            for (int ty = 0; ty < column; ty++)
                for (int tx = 0; tx < row; tx++)
                    tlThings.setCell(ty, tx, istream.readInt());
        
        } catch (Exception e) {
          throw new Exception (this.getRMSName() + "::loadMapType::" + e);
        }
    }

    void createDefaultData() throws Exception {
        try {
            ByteArrayOutputStream bstream = new ByteArrayOutputStream(12);
            DataOutputStream ostream = new DataOutputStream(bstream);
            
            // write out the number of tiles we have
            ostream.writeInt(tlThings.getColumns());
            ostream.writeInt(tlThings.getRows());

            // write the tile map
            for (int ty=0; ty < tlThings.getColumns(); ty++)
                for (int tx=0; tx < tlThings.getRows(); tx++)
                    ostream.writeInt(tlThings.getCell(ty, tx));
            
            ostream.flush();
            ostream.close();
            byte[] record = bstream.toByteArray();
            this.getRecordStore().addRecord(record, 0, record.length);  
        } catch (Exception e) {
          throw new Exception(this.getRMSName() + "::createDefaultData::" + e);
        }
    }
    
    void updateData() throws Exception {
        try {
            ByteArrayOutputStream bstream = new ByteArrayOutputStream(12);
            DataOutputStream ostream = new DataOutputStream(bstream);
            
            // write out the number of tiles we have
            ostream.writeInt(tlThings.getColumns());
            ostream.writeInt(tlThings.getRows());

            // write the tile map
            for (int ty=0; ty < tlThings.getColumns(); ty++)
                for (int tx=0; tx < tlThings.getRows(); tx++)
                    ostream.writeInt(tlThings.getCell(ty, tx));
            
            ostream.flush();
            ostream.close();
            byte[] record = bstream.toByteArray();
            this.getRecordStore().setRecord(1, record, 0, record.length);
        } catch (Exception e) {
            throw new Exception(this.getRMSName() + "::createDefaultData::" + e);
        }
    }
}
